﻿#include "ZhConvertclass.h"
#include <qsciscintilla.h>

#include "BoyerMooreU.h"
#include <QMessageBox>
#include <string>
#include <locale>
#include <codecvt>
#include <QTextCodec>
#include <QProcess>
#include <Shlwapi.h>
#include "Windows.h"
#include "Scintilla.h"


extern std::function<QsciScintilla* (QWidget*)> s_getCurEdit;
const wchar_t* STradFix = TEXT("./plugin/SipTradFix.txt");

// 判断文件是否存在
bool isFileExists_ifstream(string& name) {

	ifstream fin(name.c_str());
	return fin.good();
}

// 将 std::wstring 转换为 QString (更安全)
QString wstringToQString(const std::wstring& wstr) {
	return QString::fromStdWString(wstr);
}

// 将 QString 转换为 std::wstring (更安全)
std::wstring qstringToWString(const QString& qstr) {
	return qstr.toStdWString();
}

// 使用 Windows API 进行繁体转简体 (Unicode 版本)
QString convertToSimplified(const QString& text) {
	if (text.isEmpty()) {
		return text;
	}
	std::wstring source = qstringToWString(text);
	// 获取所需缓冲区大小
	int requiredLength = LCMapStringW(MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT),
		LCMAP_SIMPLIFIED_CHINESE,
		source.c_str(), static_cast<int>(source.length()),
		nullptr, 0);
	if (requiredLength <= 0) {
		return text; // 转换失败，返回原文本
	}

	// 分配缓冲区并执行转换
	std::unique_ptr<wchar_t[]> buffer(new wchar_t[requiredLength + 1]());
	int resultLength = LCMapStringW(MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT),
		LCMAP_SIMPLIFIED_CHINESE,
		source.c_str(), static_cast<int>(source.length()),
		buffer.get(), requiredLength);
	if (resultLength <= 0) {
		return text; // 转换失败，返回原文本
	}

	return wstringToQString(std::wstring(buffer.get(), resultLength));
}

// 使用 Windows API 进行简体转繁体 (Unicode 版本)
QString convertToTraditional(const QString& text) {
	if (text.isEmpty()) {
		return text;
	}
	std::wstring source = qstringToWString(text);
	// 获取所需缓冲区大小
	int requiredLength = LCMapStringW(MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL), SORT_DEFAULT),
		LCMAP_TRADITIONAL_CHINESE,
		source.c_str(), static_cast<int>(source.length()),
		nullptr, 0);
	if (requiredLength <= 0) {
		return text; // 转换失败，返回原文本
	}

	// 分配缓冲区并执行转换
	std::unique_ptr<wchar_t[]> buffer(new wchar_t[requiredLength + 1]());
	int resultLength = LCMapStringW(MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL), SORT_DEFAULT),
		LCMAP_TRADITIONAL_CHINESE,
		source.c_str(), static_cast<int>(source.length()),
		buffer.get(), requiredLength);
	if (resultLength <= 0) {
		return text; // 转换失败，返回原文本
	}

	return wstringToQString(std::wstring(buffer.get(), resultLength));
}


// convert string to wstring
inline std::wstring to_wide_string(const std::string& input)
{
	std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
	return converter.from_bytes(input);
}

// convert wstring to string 
inline std::string to_byte_string(const std::wstring& input)
{
	std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
	return converter.to_bytes(input);
}


ZhConvertClass::ZhConvertClass(QObject* parent, QWidget* pNotepad)
	: QObject(parent)
{
	m_pNotepad = pNotepad;
	size_t count = 0;
	string file = to_byte_string(STradFix);

	if (isFileExists_ifstream(file))
	{
		correctionTable_ = ReadConvertTable(file.c_str(), count);//读取转换校正表
	}
	else
	{
		correctionTable_ = nullptr;
	}
}

ZhConvertClass::~ZhConvertClass()
{
	if (correctionTable_) {
		// Safely delete the correction table
		for (auto* node : *correctionTable_) {
			if (node) {
				delete[] node->simp; // Assuming simp is the allocated member to delete
				delete node;
			}
		}
		delete correctionTable_;
		correctionTable_ = nullptr;
	}
}

// 设置或替换文本
void ZhConvertClass::setScintText(const QString& text, bool isSelection)  {
	auto sci = s_getCurEdit(m_pNotepad);
	if (!sci) {
		return;
	}

	QByteArray utf8Bytes = text.toUtf8();
	if (isSelection) {
		sci->SendScintilla(SCI_REPLACESEL, (utf8Bytes.constData()));
	}
	else {
		sci->SendScintilla(SCI_SETTEXT, (utf8Bytes.constData()));
	}
}

// 应用校正表
QString applyCorrectionsTrad(const QString& text, const NodeList* corrections) {
	if (!corrections || corrections->empty()) {
		return text;
	}

	QString result = text;
	for (const auto* node : *corrections) {
		if (node && node->simp && node->trad) {
			// QString::replace is safe and handles UTF-16 correctly
			result.replace(QString::fromWCharArray(node->simp), QString::fromWCharArray(node->trad));
		}
	}
	return result;
}

// 获取当前文本或选中文本
QString ZhConvertClass::getCurrentText(bool& isSelection)  {
	auto sci =  s_getCurEdit(m_pNotepad);
	if (!sci) {
		isSelection = false;
		return QString();
	}

	long startPos = sci->SendScintilla(SCI_GETSELECTIONSTART);
	long endPos = sci->SendScintilla(SCI_GETSELECTIONEND);

	isSelection = (startPos != endPos);

	if (isSelection) {
		// SCI_GETSELTEXT allocates memory, we must free it.
		long length = sci->SendScintilla(SCI_GETSELECTIONEND) - sci->SendScintilla(SCI_GETSELECTIONSTART);
		std::unique_ptr<char[]> buffer(new char[length + 1]());

		sci->SendScintilla(SCI_GETSELTEXT, length + 1, buffer.get());

		if (buffer) {
			QString text = QString::fromUtf8(buffer.get());
			return text;
		}
		return QString();
	}
	else {
		// Get full text
		long length = sci->SendScintilla(SCI_GETTEXTLENGTH);
		if (length <= 0) {
			return QString();
		}
		std::unique_ptr<char[]> buffer(new char[length + 1]());
		sci->SendScintilla(SCI_GETTEXT, length + 1, buffer.get());
		return QString::fromUtf8(buffer.get());
	}
}

void ZhConvertClass::on_TraToSimple()
{
	bool isSelection = false;
	QString originalText = getCurrentText(isSelection);
	if (originalText.isEmpty()) {
		return;
	}

	QString simplifiedText = convertToSimplified(originalText);
	setScintText(simplifiedText, isSelection);

}

void ZhConvertClass::on_SimpletoTra()
{
	bool isSelection = false;
	QString intext_ = getCurrentText(isSelection);
	if (intext_.isEmpty()) {
		return;
	}

	QString traditionalText = convertToTraditional(intext_);
	QString correctedText = applyCorrectionsTrad(traditionalText, correctionTable_);

	setScintText(correctedText, isSelection);
}

void ZhConvertClass::on_OpenTradFix()
{	
	string file = to_byte_string(STradFix);

	if (!isFileExists_ifstream(file))
	{
		QMessageBox::warning(NULL, "Warning", "Error Message: file not exist, Plaese cpoy SipTradFix.txt to  plugin folder");
		return;
	}
	else
	{
		QProcess process;
		QString filePath = QString::fromStdString(file);;
		filePath.replace("/", "\\"); // 只能识别 "\"
		QString cmd = QString("explorer.exe /select,\"%1\"").arg(filePath);
		process.startDetached(cmd);
	}

}

void ZhConvertClass::on_ChangeFix()
{
	/*to do */
}

